package br.puc.casas.dao.impl;

import org.hibernate.Session;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.SessionHolder;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.support.TransactionSynchronizationManager;

public class SingleSessionHibernateTransactionManager extends
		HibernateTransactionManager {
	private static final long serialVersionUID = -1721565757122033487L;

	private HibernateHelper hibernateHelper;

	private static final ThreadLocal<Integer> sincronizador = new ThreadLocal<Integer>() {
		@Override
		protected Integer initialValue() {
			return Integer.valueOf(0);
		}
	};

	public HibernateHelper getHibernateHelper() {
		return hibernateHelper;
	}

	public void setHibernateHelper(HibernateHelper hibernateHelper) {
		this.hibernateHelper = hibernateHelper;
	}

	protected Session getSession() {
		return hibernateHelper.getSession();
	}

	@Override
	protected Object doGetTransaction() {
		SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
				.getResource(getSessionFactory());
		if (sessionHolder == null) {
			TransactionSynchronizationManager.bindResource(hibernateHelper
					.getSessionFactory(), new SessionHolder(hibernateHelper
					.getSession()));
			SingleSessionHibernateTransactionManager.sincronizador.set(Integer
					.valueOf(0));
		}

		return super.doGetTransaction();
	}

	@Override
	protected void doBegin(Object transaction, TransactionDefinition definition) {
		int sincronizador = SingleSessionHibernateTransactionManager.sincronizador
				.get().intValue() + 1;
		SingleSessionHibernateTransactionManager.sincronizador.set(Integer
				.valueOf(sincronizador));

		super.doBegin(transaction, definition);
	}

	@Override
	protected void doCleanupAfterCompletion(Object transaction) {
		int sincronizador = SingleSessionHibernateTransactionManager.sincronizador
				.get().intValue() - 1;
		if (sincronizador == 0) {
			TransactionSynchronizationManager.unbindResource(hibernateHelper
					.getSessionFactory());
		}
		SingleSessionHibernateTransactionManager.sincronizador.set(Integer
				.valueOf(sincronizador));
		super.doCleanupAfterCompletion(transaction);
	}
}
